<!DOCTYPE html>
<html lang="zh">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>数独游戏</title>
    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        body {
            background-color: #f8f9fa;
            font-family: 'Arial', sans-serif;
        }

        .game-container {
            max-width: 800px;
            margin: 20px auto;
            padding: 20px;
            background-color: white;
            border-radius: 10px;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
        }

        .game-header {
            margin-bottom: 20px;
            text-align: center;
        }

        .game-controls {
            display: flex;
            justify-content: space-between;
            flex-wrap: wrap;
            margin-bottom: 20px;
            gap: 10px;
        }

        .game-stats {
            display: flex;
            justify-content: space-around;
            margin-bottom: 20px;
            background-color: #f1f1f1;
            padding: 10px;
            border-radius: 5px;
            flex-wrap: wrap;
            gap: 10px;
        }

        .sudoku-board {
            display: grid;
            grid-template-columns: repeat(9, 1fr);
            gap: 1px;
            background-color: #333;
            border: 2px solid #333;
            margin: 0 auto;
            max-width: 500px;
        }

        .cell {
            aspect-ratio: 1;
            display: flex;
            align-items: center;
            justify-content: center;
            background-color: white;
            font-size: 1.5rem;
            font-weight: bold;
            cursor: pointer;
            user-select: none;
            transition: all 0.2s;
            position: relative;
        }

        .cell:hover {
            background-color: #f0f0f0;
        }

        .cell.given {
            background-color: #f8f9fa;
            color: #000;
            cursor: default;
        }

        /* 选中格子的样式 - 更明显的视觉效果 */
        .cell.selected {
            background-color: #007bff;
            color: white;
            transform: scale(0.95);
            box-shadow: 0 0 0 2px #0056b3;
            z-index: 1;
        }

        /* 高亮相关单元格的样式 */
        .cell.highlighted {
            background-color: #e6f7ff;
        }

        /* 相同数字高亮 */
        .cell.same-number {
            background-color: #b8daff;
        }

        .cell.error {
            color: #dc3545;
        }

        .cell.notes {
            font-size: 0.7rem;
            color: #6c757d;
            line-height: 1;
            padding-top: 2px;
        }

        /* 3x3区块边框 */
        .cell:nth-child(3n) {
            border-right: 2px solid #333;
        }

        .cell:nth-child(9n) {
            border-right: none;
        }

        .cell:nth-child(n+19):nth-child(-n+27),
        .cell:nth-child(n+46):nth-child(-n+54) {
            border-bottom: 2px solid #333;
        }

        .number-pad {
            display: grid;
            grid-template-columns: repeat(5, 1fr);
            gap: 10px;
            margin-top: 20px;
            max-width: 500px;
            margin-left: auto;
            margin-right: auto;
        }

        .number-btn {
            aspect-ratio: 1;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 1.5rem;
            font-weight: bold;
            border-radius: 5px;
            cursor: pointer;
            user-select: none;
        }

        .notes-toggle {
            grid-column: span 2;
            aspect-ratio: unset;
        }

        @media (max-width: 576px) {
            .cell {
                font-size: 1.2rem;
            }

            .number-btn {
                font-size: 1.2rem;
            }

            .game-controls {
                flex-direction: column;
                align-items: center;
            }
        }

        .modal-content {
            border-radius: 10px;
        }

        /* 笔记数字的小网格 */
        .notes-container {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            grid-template-rows: repeat(3, 1fr);
            width: 100%;
            height: 100%;
        }

        .notes-container span {
            display: flex;
            align-items: center;
            justify-content: center;
        }
    </style>
</head>

<body>
    <div class="container game-container">
        <div class="game-header">
            <h1 class="text-primary">数独游戏</h1>
            <p class="lead">填入数字1-9，使每行、每列和每个3×3宫格都包含1-9且不重复</p>
        </div>

        <div class="game-controls">
            <div class="btn-group">
                <button type="button" class="btn btn-outline-primary dropdown-toggle" data-bs-toggle="dropdown"
                    aria-expanded="false">
                    难度
                </button>
                <ul class="dropdown-menu">
                    <li><a class="dropdown-item" href="#" data-difficulty="easy">简单</a></li>
                    <li><a class="dropdown-item" href="#" data-difficulty="medium">中等</a></li>
                    <li><a class="dropdown-item" href="#" data-difficulty="hard">困难</a></li>
                    <li><a class="dropdown-item" href="#" data-difficulty="expert">专家</a></li>
                </ul>
            </div>
            <div>
                <button id="new-game-btn" class="btn btn-primary">新游戏</button>
                <button id="hint-btn" class="btn btn-info">提示</button>
                <button id="check-btn" class="btn btn-warning">检查</button>
                <button id="solve-btn" class="btn btn-danger">解答</button>
            </div>
        </div>

        <div class="game-stats">
            <div>
                <h5>时间</h5>
                <div id="timer">00:00</div>
            </div>
            <div>
                <h5>错误</h5>
                <div id="mistakes">0</div>
            </div>
            <div>
                <h5>提示</h5>
                <div id="hints-used">0</div>
            </div>
        </div>

        <div class="sudoku-board" id="sudoku-board">
            <!-- 81个格子将通过JavaScript动态生成 -->
        </div>

        <div class="number-pad">
            <div class="number-btn btn btn-outline-primary" data-number="1">1</div>
            <div class="number-btn btn btn-outline-primary" data-number="2">2</div>
            <div class="number-btn btn btn-outline-primary" data-number="3">3</div>
            <div class="number-btn btn btn-outline-primary" data-number="4">4</div>
            <div class="number-btn btn btn-outline-primary" data-number="5">5</div>
            <div class="number-btn btn btn-outline-primary" data-number="6">6</div>
            <div class="number-btn btn btn-outline-primary" data-number="7">7</div>
            <div class="number-btn btn btn-outline-primary" data-number="8">8</div>
            <div class="number-btn btn btn-outline-primary" data-number="9">9</div>
            <div class="number-btn btn btn-outline-secondary" id="clear-btn">清除</div>
            <div class="number-btn btn btn-outline-info notes-toggle" id="notes-btn">笔记模式</div>
        </div>
    </div>

    <!-- 游戏结束模态框 -->
    <div class="modal fade" id="gameOverModal" tabindex="-1" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header bg-success text-white">
                    <h5 class="modal-title">恭喜你！</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body text-center">
                    <h4>你成功完成了数独！</h4>
                    <p>用时: <span id="final-time"></span></p>
                    <p>错误次数: <span id="final-mistakes"></span></p>
                    <p>使用提示: <span id="final-hints"></span></p>
                    <p>难度: <span id="final-difficulty"></span></p>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                    <button id="play-again-btn" type="button" class="btn btn-primary">再玩一次</button>
                </div>
            </div>
        </div>
    </div>

    <!-- jQuery和Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
    <noscript>
        <style>
            body {
                display: none !important;
            }
        </style>
        <meta http-equiv="refresh" content="0; url=about:blank">
    </noscript>
    <script src="security.js"></script>

    <script>
        $(document).ready(function () {
            // 游戏变量
            let board = Array(9).fill().map(() => Array(9).fill(0));
            let solution = Array(9).fill().map(() => Array(9).fill(0));
            let given = Array(9).fill().map(() => Array(9).fill(false));
            let notes = Array(9).fill().map(() => Array(9).fill().map(() => []));
            let selectedCell = null;
            let timerInterval;
            let seconds = 0;
            let mistakes = 0;
            let hintsUsed = 0;
            let currentDifficulty = "medium";
            let isNotesMode = false;
            const difficulties = {
                easy: { name: "简单", givenCells: 45 },
                medium: { name: "中等", givenCells: 35 },
                hard: { name: "困难", givenCells: 28 },
                expert: { name: "专家", givenCells: 22 }
            };

            // 初始化游戏
            initGame();

            // 初始化游戏函数
            function initGame() {
                // 重置游戏状态
                board = Array(9).fill().map(() => Array(9).fill(0));
                given = Array(9).fill().map(() => Array(9).fill(false));
                notes = Array(9).fill().map(() => Array(9).fill().map(() => []));
                selectedCell = null;
                seconds = 0;
                mistakes = 0;
                hintsUsed = 0;
                clearInterval(timerInterval);
                updateStats();
                isNotesMode = false;
                $('#notes-btn').removeClass('btn-info').addClass('btn-outline-info');

                // 生成数独题目
                generateSudoku();

                // 创建游戏板
                createBoard();

                // 开始计时
                timerInterval = setInterval(updateTimer, 1000);
            }

            // 生成数独题目
            function generateSudoku() {
                // 生成完整解
                generateSolution();

                // 复制解
                solution = board.map(row => [...row]);

                // 根据难度挖空
                const givenCells = difficulties[currentDifficulty].givenCells;
                let cellsToRemove = 81 - givenCells;

                while (cellsToRemove > 0) {
                    const row = Math.floor(Math.random() * 9);
                    const col = Math.floor(Math.random() * 9);

                    if (board[row][col] !== 0) {
                        const temp = board[row][col];
                        board[row][col] = 0;

                        // 检查是否有唯一解
                        if (countSolutions(JSON.parse(JSON.stringify(board))) === 1) {
                            cellsToRemove--;
                        } else {
                            board[row][col] = temp;
                        }
                    }
                }

                // 标记给定的数字
                for (let row = 0; row < 9; row++) {
                    for (let col = 0; col < 9; col++) {
                        given[row][col] = board[row][col] !== 0;
                    }
                }
            }

            // 生成完整解
            function generateSolution() {
                // 重置板
                board = Array(9).fill().map(() => Array(9).fill(0));

                // 填充对角线上的3x3方块
                fillDiagonalBoxes();

                // 解决剩余部分
                solveSudoku();
            }

            // 填充对角线上的3x3方块
            function fillDiagonalBoxes() {
                for (let box = 0; box < 9; box += 3) {
                    fillBox(box, box);
                }
            }

            // 填充一个3x3方块
            function fillBox(row, col) {
                const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];
                shuffleArray(nums);

                let index = 0;
                for (let i = 0; i < 3; i++) {
                    for (let j = 0; j < 3; j++) {
                        board[row + i][col + j] = nums[index++];
                    }
                }
            }

            // 解决数独
            function solveSudoku() {
                for (let row = 0; row < 9; row++) {
                    for (let col = 0; col < 9; col++) {
                        if (board[row][col] === 0) {
                            for (let num = 1; num <= 9; num++) {
                                if (isValidPlacement(row, col, num)) {
                                    board[row][col] = num;

                                    if (solveSudoku()) {
                                        return true;
                                    }

                                    board[row][col] = 0;
                                }
                            }
                            return false;
                        }
                    }
                }
                return true;
            }

            // 计算解的数量
            function countSolutions(grid) {
                let count = 0;

                function backtrack() {
                    for (let row = 0; row < 9; row++) {
                        for (let col = 0; col < 9; col++) {
                            if (grid[row][col] === 0) {
                                for (let num = 1; num <= 9; num++) {
                                    if (isValidPlacementForGrid(grid, row, col, num)) {
                                        grid[row][col] = num;

                                        if (backtrack()) {
                                            count++;
                                            if (count > 1) return true; // 提前终止
                                        }

                                        grid[row][col] = 0;
                                    }
                                }
                                return false;
                            }
                        }
                    }
                    return true;
                }

                backtrack();
                return count;
            }

            // 检查数字放置是否有效（针对当前board）
            function isValidPlacement(row, col, num) {
                // 检查行
                for (let x = 0; x < 9; x++) {
                    if (board[row][x] === num) return false;
                }

                // 检查列
                for (let x = 0; x < 9; x++) {
                    if (board[x][col] === num) return false;
                }

                // 检查3x3方块
                const boxRow = Math.floor(row / 3) * 3;
                const boxCol = Math.floor(col / 3) * 3;

                for (let i = 0; i < 3; i++) {
                    for (let j = 0; j < 3; j++) {
                        if (board[boxRow + i][boxCol + j] === num) return false;
                    }
                }

                return true;
            }

            // 检查数字放置是否有效（针对任意grid）
            function isValidPlacementForGrid(grid, row, col, num) {
                // 检查行
                for (let x = 0; x < 9; x++) {
                    if (grid[row][x] === num) return false;
                }

                // 检查列
                for (let x = 0; x < 9; x++) {
                    if (grid[x][col] === num) return false;
                }

                // 检查3x3方块
                const boxRow = Math.floor(row / 3) * 3;
                const boxCol = Math.floor(col / 3) * 3;

                for (let i = 0; i < 3; i++) {
                    for (let j = 0; j < 3; j++) {
                        if (grid[boxRow + i][boxCol + j] === num) return false;
                    }
                }

                return true;
            }

            // 创建游戏板
            function createBoard() {
                $('#sudoku-board').empty();

                for (let row = 0; row < 9; row++) {
                    for (let col = 0; col < 9; col++) {
                        const cell = $('<div class="cell"></div>');
                        cell.attr('data-row', row);
                        cell.attr('data-col', col);

                        if (board[row][col] !== 0) {
                            cell.text(board[row][col]);
                            cell.addClass('given');
                        }

                        cell.click(function () {
                            selectCell($(this));
                        });

                        $('#sudoku-board').append(cell);
                    }
                }
            }

            // 选择单元格
            function selectCell(cell) {
                // 取消之前的选择
                if (selectedCell) {
                    selectedCell.removeClass('selected');
                    highlightRelatedCells(selectedCell, false);
                }

                // 如果是给定的数字，不能选择
                if (cell.hasClass('given')) {
                    selectedCell = null;
                    return;
                }

                // 选择新单元格
                selectedCell = cell;
                cell.addClass('selected');
                highlightRelatedCells(cell, true);
            }

            // 高亮相关单元格
            function highlightRelatedCells(cell, highlight) {
                const row = parseInt(cell.attr('data-row'));
                const col = parseInt(cell.attr('data-col'));
                const value = board[row][col];

                // 移除所有高亮和相同数字高亮
                $('.cell').removeClass('highlighted same-number');

                if (highlight) {
                    // 高亮同行同列
                    for (let i = 0; i < 9; i++) {
                        $(`.cell[data-row="${row}"][data-col="${i}"]`).addClass('highlighted');
                        $(`.cell[data-row="${i}"][data-col="${col}"]`).addClass('highlighted');
                    }

                    // 高亮同3x3方块
                    const boxRow = Math.floor(row / 3) * 3;
                    const boxCol = Math.floor(col / 3) * 3;

                    for (let i = 0; i < 3; i++) {
                        for (let j = 0; j < 3; j++) {
                            $(`.cell[data-row="${boxRow + i}"][data-col="${boxCol + j}"]`).addClass('highlighted');
                        }
                    }

                    // 高亮相同数字（不包括当前选中的单元格）
                    if (value !== 0) {
                        $('.cell').each(function () {
                            const cellRow = parseInt($(this).attr('data-row'));
                            const cellCol = parseInt($(this).attr('data-col'));
                            if (board[cellRow][cellCol] === value && !(cellRow === row && cellCol === col)) {
                                $(this).addClass('same-number');
                            }
                        });
                    }
                }
            }

            // 填入数字
            function fillNumber(num) {
                if (!selectedCell) return;

                const row = parseInt(selectedCell.attr('data-row'));
                const col = parseInt(selectedCell.attr('data-col'));

                if (isNotesMode) {
                    // 笔记模式
                    const index = notes[row][col].indexOf(num);

                    if (index === -1) {
                        notes[row][col].push(num);
                        notes[row][col].sort();
                    } else {
                        notes[row][col].splice(index, 1);
                    }

                    updateNotesDisplay(row, col);
                } else {
                    // 正常模式
                    board[row][col] = num;
                    selectedCell.text(num === 0 ? '' : num);
                    selectedCell.removeClass('error notes');

                    // 检查是否正确
                    if (num !== 0 && num !== solution[row][col]) {
                        selectedCell.addClass('error');
                        mistakes++;
                        updateStats();
                    }

                    // 检查游戏是否完成
                    checkCompletion();
                }
            }

            // 更新笔记显示
            function updateNotesDisplay(row, col) {
                const cell = $(`.cell[data-row="${row}"][data-col="${col}"]`);
                cell.empty();
                cell.removeClass('error');

                if (notes[row][col].length > 0) {
                    cell.addClass('notes');
                    const notesContainer = $('<div class="notes-container"></div>');

                    // 创建3x3网格显示笔记数字
                    for (let i = 1; i <= 9; i++) {
                        const note = $('<span></span>');
                        if (notes[row][col].includes(i)) {
                            note.text(i);
                        }
                        notesContainer.append(note);
                    }

                    cell.append(notesContainer);
                } else {
                    cell.removeClass('notes');
                    if (board[row][col] !== 0) {
                        cell.text(board[row][col]);
                    }
                }
            }

            // 清除单元格
            function clearCell() {
                if (!selectedCell) return;

                const row = parseInt(selectedCell.attr('data-row'));
                const col = parseInt(selectedCell.attr('data-col'));

                board[row][col] = 0;
                notes[row][col] = [];
                selectedCell.text('');
                selectedCell.removeClass('error notes');
            }

            // 切换笔记模式
            function toggleNotesMode() {
                isNotesMode = !isNotesMode;
                $('#notes-btn').toggleClass('btn-outline-info btn-info');
            }

            // 提供提示
            function giveHint() {
                if (!selectedCell || selectedCell.hasClass('given')) return;

                const row = parseInt(selectedCell.attr('data-row'));
                const col = parseInt(selectedCell.attr('data-col'));

                if (board[row][col] === 0 || board[row][col] !== solution[row][col]) {
                    board[row][col] = solution[row][col];
                    selectedCell.text(solution[row][col]);
                    selectedCell.removeClass('error notes');
                    hintsUsed++;
                    updateStats();

                    // 检查游戏是否完成
                    checkCompletion();
                }
            }

            // 检查答案
            function checkSolution() {
                let hasErrors = false;

                for (let row = 0; row < 9; row++) {
                    for (let col = 0; col < 9; col++) {
                        const cell = $(`.cell[data-row="${row}"][data-col="${col}"]`);

                        if (!given[row][col]) {
                            if (board[row][col] !== 0 && board[row][col] !== solution[row][col]) {
                                cell.addClass('error');
                                hasErrors = true;
                            } else if (board[row][col] === solution[row][col]) {
                                cell.removeClass('error');
                            }
                        }
                    }
                }

                if (!hasErrors) {
                    alert('没有发现错误！继续加油！');
                } else {
                    mistakes++;
                    updateStats();
                }
            }

            // 显示解答
            function showSolution() {
                if (confirm('确定要显示解答吗？这将结束当前游戏。')) {
                    for (let row = 0; row < 9; row++) {
                        for (let col = 0; col < 9; col++) {
                            board[row][col] = solution[row][col];
                            const cell = $(`.cell[data-row="${row}"][data-col="${col}"]`);
                            cell.text(solution[row][col]);
                            cell.removeClass('error notes');
                        }
                    }

                    endGame();
                }
            }

            // 检查游戏是否完成
            function checkCompletion() {
                for (let row = 0; row < 9; row++) {
                    for (let col = 0; col < 9; col++) {
                        if (board[row][col] !== solution[row][col]) {
                            return false;
                        }
                    }
                }

                endGame();
                return true;
            }

            // 游戏结束
            function endGame() {
                clearInterval(timerInterval);

                // 显示结果
                $('#final-time').text($('#timer').text());
                $('#final-mistakes').text(mistakes);
                $('#final-hints').text(hintsUsed);
                $('#final-difficulty').text(difficulties[currentDifficulty].name);

                // 显示模态框
                const gameOverModal = new bootstrap.Modal(document.getElementById('gameOverModal'));
                gameOverModal.show();
            }

            // 更新游戏统计信息
            function updateStats() {
                $('#timer').text(formatTime(seconds));
                $('#mistakes').text(mistakes);
                $('#hints-used').text(hintsUsed);
            }

            // 格式化时间
            function formatTime(totalSeconds) {
                const minutes = Math.floor(totalSeconds / 60);
                const seconds = totalSeconds % 60;
                return `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
            }

            // 更新计时器
            function updateTimer() {
                seconds++;
                $('#timer').text(formatTime(seconds));
            }

            // 洗牌函数
            function shuffleArray(array) {
                for (let i = array.length - 1; i > 0; i--) {
                    const j = Math.floor(Math.random() * (i + 1));
                    [array[i], array[j]] = [array[j], array[i]];
                }
                return array;
            }

            // 事件监听
            $('.number-btn[data-number]').click(function () {
                const num = parseInt($(this).data('number'));
                fillNumber(num);
            });

            $('#clear-btn').click(clearCell);
            $('#notes-btn').click(toggleNotesMode);
            $('#hint-btn').click(giveHint);
            $('#check-btn').click(checkSolution);
            $('#solve-btn').click(showSolution);
            $('#new-game-btn').click(initGame);
            $('#play-again-btn').click(function () {
                initGame();
                $('#gameOverModal').modal('hide');
            });

            $('.dropdown-item[data-difficulty]').click(function () {
                currentDifficulty = $(this).data('difficulty');
                $('.dropdown-toggle').text('难度: ' + difficulties[currentDifficulty].name);
                initGame();
            });

            // 键盘支持
            $(document).keydown(function (e) {
                if (!selectedCell) return;

                if (e.key >= '1' && e.key <= '9') {
                    fillNumber(parseInt(e.key));
                } else if (e.key === '0' || e.key === 'Backspace' || e.key === 'Delete') {
                    clearCell();
                } else if (e.key === 'n') {
                    toggleNotesMode();
                }
            });
        });
    </script>
</body>

</html>